package com.szwistar.common.os;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.szwistar.common.comm.HttpUtils;
import com.szwistar.common.datastruct.Utils;

public class Network {
	protected static final Logger LOG = LoggerFactory.getLogger(Network.class);

	//获取本机IPv4地址
	public static List<InetAddress> getLocalHostIpv4() throws SocketException {
		Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
		List<InetAddress> ips = new LinkedList<InetAddress>();

        // 遍历所用的网络接口
        while (en.hasMoreElements()) {
            NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip
            Enumeration<InetAddress> inet = nif.getInetAddresses();
            // 遍历每一个接口绑定的所有ip
            while (inet.hasMoreElements()) {
                InetAddress ip = inet.nextElement();
                if (!ip.isLoopbackAddress() && (ip instanceof Inet4Address)) { ips.add(ip); }
            }
        }

        return ips;
	}

	// 获取本机IPv6地址
	public static List<InetAddress> getLocalHostIpv6() throws SocketException {
		Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
		List<InetAddress> ips = new LinkedList<InetAddress>();
        // 遍历所用的网络接口
        while (en.hasMoreElements())
        {
            NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip
            Enumeration<InetAddress> inet = nif.getInetAddresses();
            // 遍历每一个接口绑定的所有ip
            while (inet.hasMoreElements()) {
                InetAddress ip = inet.nextElement();
                if (!ip.isLoopbackAddress() && (ip instanceof Inet6Address)) { ips.add(ip); }
            }
        }

        return ips;
	}

	/**
	 * 打印所有网卡名称、显示名称、MAC地址
	 * */
	public static void printNetworkInterfaceInfo() {
        try {
        	 Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
        	 while (netInterfaces.hasMoreElements()) {
                NetworkInterface ni = netInterfaces.nextElement();
				System.out.printf("%s (%s)", ni.getName(), ni.getDisplayName());
				byte[] mac = ni.getHardwareAddress();
				if(mac != null) { System.out.printf(": %02X-%02X-%02X-%02X-%02X-%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); }

				Enumeration<InetAddress> address = ni.getInetAddresses();
                while(address.hasMoreElements()) {
                    InetAddress ip = address.nextElement();
                    if (ip.isAnyLocalAddress() || (ip.isLoopbackAddress()) || (!ni.supportsMulticast())) { continue; }
					System.out.print(", " + ip.toString());
                }
				System.out.println();
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

	/**
	 * 获取本机网卡 MAC 地址
	 * @param nicName
	 * @return
	 * @throws SocketException
	 */
	public static byte[] getLocalMac(String nicName) throws SocketException {
		NetworkInterface nic = NetworkInterface.getByName(nicName);
		return (nic == null) ? null : nic.getHardwareAddress();
	}

    /**
     * 通过 ARP 获取 IP 对应的 MAC
     */
	public static String getMacFromIp(String ip) throws IOException {
		Process proc = Runtime.getRuntime().exec("arp -a");
		BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
		String line;
		String os = System.getProperty("os.name");
		while( (line=in.readLine()) != null ) {
			if( !line.contains(ip) ) {
				continue;
			}
			if( os.startsWith("Windows") ) {
				String[] pics = line.toUpperCase().split("\\s+");
				in.close();
				return pics[2].replaceAll("-", "");
			}
			else {
				String[] pics = line.toUpperCase().split("\\s+");
				in.close();
				return pics[3].replaceAll(":", "");
			}
		}
		in.close();
		return null;
	}

	/**
	 * ping一个主机，检测网络是否通
	 * @param host
	 * @param timeout
	 * @return
	 * @throws IOException
	 * @throws UnknownHostException
	 */
	public static boolean ping(String host, int timeout) throws IOException {
		return InetAddress.getByName(host).isReachable(timeout);
	}

	/**
	 * 判断一个ip地址是否为内网地址
	 * @param ip
	 * @return
	 */
	public static boolean isInnerIp(String ip) {
		//如下网段为内网地址
		//10.0.0.0~10.255.255.255
		//172.16.0.0~172.31.255.255
		//192.168.0.0~192.168.255.255
	    String reg = "(10|172|192)\\.([0-1][0-9]{0,2}|[2][0-5]{0,2}|[3-9][0-9]{0,1})\\.([0-1][0-9]{0,2}|[2][0-5]{0,2}|[3-9][0-9]{0,1})\\.([0-1][0-9]{0,2}|[2][0-5]{0,2}|[3-9][0-9]{0,1})";
	    return Utils.isNotEmpty(ip) && ip.matches(reg);
	}

	/**
	 * 判断是否是一个IPv4地址
	 */
	public static boolean isIpv4Address(String ip) {
	    return Utils.isNotEmpty(ip) && ip.matches("\\d+\\.\\d+\\.\\d+\\.\\d+");
	}

	/**
	 * 获取自己的外网地址
	 * @throws Exception
	 */
	public static String getInternetIpv4() throws Exception {
		return HttpUtils.request("http://www.szwistar.com/getip", null, null).trim();
	}
}
